<?php

namespace app\server\amqp\controller;

use app\common\model\Config;
use app\server\amqp\model\ConnectionUtil;
use GuzzleHttp\Client;
use JMessage\IM\Message;
use JMessage\JMessage;
use variant\library\vari\Log;

class Im
{

    private $_host;
    private $_port;
    private $_virtualHost;
    private $_accessKey;
    private $_accessSecret;
    private $_resourceOwnerId;
    private $_queue = [];
    private $_connection;

    private $_client;
    private $_httpClient;

    private $server;

    /**
     * Im constructor.
     * @param $server
     */
    public function __construct($server)
    {
        $this->server = $server;
        $this->_host = Config::get('host', 'amqp');
        $this->_port = Config::get('port', 'amqp');
        $this->_virtualHost = Config::get('virtual_host', 'amqp');
        $this->_accessKey = Config::get('access_key', 'amqp');
        $this->_accessSecret = Config::get('access_secret', 'amqp');
        $this->_resourceOwnerId = Config::get('resource_owner_id', 'amqp');
        $this->_queue = Config::get('queue', 'amqp');

        $key = Config::get('app_key', 'im');
        $secret = Config::get('master_secret', 'im');
        $this->_client = new JMessage($key, $secret);
        $this->_httpClient = new Client();
    }

    public function run()
    {

        if (!isset($this->connection) || $this->connection->isConnected() === false) {
           /* echo 'im' . PHP_EOL;
            $res = $this->memory_usage();
            echo $res .PHP_EOL;*/
            $this->_connection = new ConnectionUtil([
                $this->_host, $this->_port, $this->_virtualHost, $this->_accessKey, $this->_accessSecret, $this->_resourceOwnerId,
                'host' => $this->_host,
                'port' => $this->_port,
                'virtualHost' => $this->_virtualHost,
                'accessKey' => $this->_accessKey,
                'accessSecret' => $this->_accessSecret,
                'resourceOwnerId' => $this->_resourceOwnerId
            ]);
        }

    }

    public function memory_usage() {
        $memory     = ( ! function_exists('memory_get_usage')) ? '0' : round(memory_get_usage()/1024/1024, 2);
        return $memory;
    }

    /**
     * 订阅IM消息
     */
    public function index()
    {

        try {
            $this->run();
            $connection = $this->_connection->getConnection();
            $channel = $connection->channel();
            $im = Config::get('queue_im', 'amqp');
            $channel->queue_declare($im, true, false, false, false);
            $callback = function ($msg) {
                Log::instance()->notice('amqp: ' . $msg->body);
                $res = $this->_init(json_decode($msg->body, true));
                Log::instance()->notice(var_export($res, true));
                $msg->delivery_info['channel']->basic_ack($msg->delivery_info['delivery_tag']);
            };
            $channel->basic_consume($im, '', false, true, false, false, $callback);
            while (count($channel->callbacks)) {
                $this->run();
                $channel->wait();
            }
            $channel->close();
            $connection->close();
        } catch (\Exception $exception) {
            Log::instance()->warning('IM:' . $exception->getMessage());
            $this->index();
        }

    }


    /**
     * @param array $params
     * @return bool|string
     */
    private function _init($params = [])
    {
        if (empty($params['to_user']) || !is_array($params['to_user'])) {
            return 'to_user must be an array!';
        }
        if (empty($params['buttons']) || !is_array($params['buttons'])) {
            return 'buttons must be an array';
        }
        $buttons = [];

        foreach ($params['buttons'] as $k => $v) {
            if (empty($v['title']) || empty($v['url'])) {
                echo 'IM_PUSH_MESSAGE_FAILED';
            }
            $buttons[$k] = [];
            $buttons[$k]['title'] = htmlspecialchars($v['title'], ENT_QUOTES);
            $buttons[$k]['url'] = htmlspecialchars($v['url'], ENT_QUOTES);
        }

        /**
         * 自定义通知
         */
        $messageBody = [
            'msg_type' => 'CUSTOM_NOTICE',
            'msg_content' => [
                //缩略图
                'thumb' => $params['thumb'] ?? null,
                //原图
                'original_img' => $params['original_img'] ?? null,
                //标题
                'title' => htmlspecialchars($params['title'] ?? null, ENT_QUOTES),
                //描述
                'description' => htmlspecialchars($params['description'] ?? null, ENT_QUOTES),
                //时间
                'createTime' => intval($params['createTime'] ?? null),
                //详情地址 默认按钮动作
                'url' => htmlspecialchars($params['url'] ?? null, ENT_QUOTES),
                'buttons' => $buttons
            ]
        ];

        /**
         * 推送客户端
         */
        $info = [
            'type' => 'message',
            'to_user' => $params['to_user'],
            'body' => [
                'title' => htmlspecialchars($params['title'] ?? null, ENT_QUOTES),
                'original_img' => $params['original_img'] ?? null,
                'thumb' => $params['thumb'] ?? null,
                'description' => htmlspecialchars($params['description'] ?? null, ENT_QUOTES),
                'createTime' => intval($params['createTime'] ?? null),
                'url' => htmlspecialchars($params['url'] ?? null, ENT_QUOTES),
            ]
        ];
        $pushDevice = [
            'body' => json_encode($info)
        ];

        $httpRes = $this->_httpClient->post(Config::get('to_device_url', 'im'), $pushDevice);
        $httpRes = json_decode(strval($httpRes->getBody()), true);
        if ($httpRes['status'] != 0) {
            Log::instance()->error(var_export($httpRes, true));
        }

        //目标用户
        foreach ($params['to_user'] as $v) {
            $target = 'user_' . $v;
            $res = $this->sendSingleMessage($target, $messageBody);
            Log::instance()->notice(var_export($res, true));
        }
        return true;
    }

    /**
     * 更新发送消息状态
     *
     * @param $target
     * @param $content
     * @return bool
     */
    private function sendSingleMessage($target, $content)
    {
        $message = new Message($this->_client);
        $from = [
            'type' => 'admin',
            'id' => '10001'

        ];
        $target = [
            'type' => 'single',
            'id' => $target
        ];
        $msg = [
            'text' => $content['msg_content']['description'],
            'extras' => $content
        ];

        $r = $message->sendText("1", $from, $target, $msg);

        if (is_string($r)) {
            //记录错误记录
            Log::instance()->error('im 消息发送超时 ' . $r);
            return false;
        }
        if ($r['http_code'] == 201) {
            return true;
        }
        //记录错误记录
        Log::instance()->error('im 消息发送失败 ' . var_export($r, true));
        return false;
    }
}